/**
 * 查询缓存管理器
 * 
 * 用于管理API请求缓存，避免重复请求
 */

// 缓存项接口
interface CacheItem<T> {
  data: T;
  timestamp: number;
  expiresAt: number;
}

// 缓存配置接口
interface CacheConfig {
  // 默认缓存过期时间（毫秒）
  defaultTtl: number;
  // 最大缓存项数量
  maxItems: number;
  // 是否启用持久化存储
  persistToStorage: boolean;
  // 持久化存储键
  storageKey: string;
  // 是否启用自动清理过期缓存
  autoCleanup: boolean;
  // 自动清理间隔（毫秒）
  cleanupInterval: number;
}

/**
 * 查询缓存管理器类
 * 
 * 提供缓存管理功能，支持缓存过期、自动清理、持久化存储等
 */
export class QueryCache {
  private cache: Map<string, CacheItem<any>>;
  private config: CacheConfig;
  private cleanupTimer: NodeJS.Timeout | null = null;

  /**
   * 构造函数
   * 
   * @param config 缓存配置
   */
  constructor(config: Partial<CacheConfig> = {}) {
    this.config = {
      defaultTtl: 5 * 60 * 1000, // 默认5分钟
      maxItems: 100,
      persistToStorage: false,
      storageKey: 'query_cache',
      autoCleanup: true,
      cleanupInterval: 60 * 1000, // 默认1分钟
      ...config
    };

    // 初始化缓存
    this.cache = new Map<string, CacheItem<any>>();

    // 从持久化存储加载缓存
    if (this.config.persistToStorage) {
      this.loadFromStorage();
    }

    // 启动自动清理
    if (this.config.autoCleanup) {
      this.startCleanupTimer();
    }
  }

  /**
   * 设置缓存项
   * 
   * @param key 缓存键
   * @param data 缓存数据
   * @param ttl 过期时间（毫秒），默认使用配置中的defaultTtl
   * @returns 是否设置成功
   */
  set<T>(key: string, data: T, ttl: number = this.config.defaultTtl): boolean {
    try {
      // 检查缓存大小
      if (this.cache.size >= this.config.maxItems && !this.cache.has(key)) {
        // 如果缓存已满且不是更新现有项，则删除最旧的项
        this.removeOldestItem();
      }

      const now = Date.now();
      const cacheItem: CacheItem<T> = {
        data,
        timestamp: now,
        expiresAt: now + ttl
      };

      // 设置缓存
      this.cache.set(key, cacheItem);

      // 持久化缓存
      if (this.config.persistToStorage) {
        this.saveToStorage();
      }

      return true;
    } catch (error) {
      console.error('缓存设置失败:', error);
      return false;
    }
  }

  /**
   * 获取缓存项
   * 
   * @param key 缓存键
   * @returns 缓存数据，如果不存在或已过期则返回undefined
   */
  get<T>(key: string): T | undefined {
    try {
      const cacheItem = this.cache.get(key) as CacheItem<T> | undefined;

      // 检查缓存项是否存在
      if (!cacheItem) {
        return undefined;
      }

      // 检查缓存项是否过期
      if (Date.now() > cacheItem.expiresAt) {
        this.delete(key);
        return undefined;
      }

      return cacheItem.data;
    } catch (error) {
      console.error('缓存获取失败:', error);
      return undefined;
    }
  }

  /**
   * 检查缓存项是否存在且未过期
   * 
   * @param key 缓存键
   * @returns 是否存在且未过期
   */
  has(key: string): boolean {
    try {
      const cacheItem = this.cache.get(key);
      
      // 检查缓存项是否存在
      if (!cacheItem) {
        return false;
      }

      // 检查缓存项是否过期
      if (Date.now() > cacheItem.expiresAt) {
        this.delete(key);
        return false;
      }

      return true;
    } catch (error) {
      console.error('缓存检查失败:', error);
      return false;
    }
  }

  /**
   * 删除缓存项
   * 
   * @param key 缓存键
   * @returns 是否删除成功
   */
  delete(key: string): boolean {
    try {
      const result = this.cache.delete(key);

      // 持久化缓存
      if (result && this.config.persistToStorage) {
        this.saveToStorage();
      }

      return result;
    } catch (error) {
      console.error('缓存删除失败:', error);
      return false;
    }
  }

  /**
   * 清空缓存
   */
  clear(): void {
    try {
      this.cache.clear();

      // 持久化缓存
      if (this.config.persistToStorage) {
        this.saveToStorage();
      }
    } catch (error) {
      console.error('缓存清空失败:', error);
    }
  }

  /**
   * 获取缓存大小
   * 
   * @returns 缓存项数量
   */
  size(): number {
    return this.cache.size;
  }

  /**
   * 获取所有缓存键
   * 
   * @returns 缓存键数组
   */
  keys(): string[] {
    return Array.from(this.cache.keys());
  }

  /**
   * 获取所有缓存项
   * 
   * @returns 缓存项数组
   */
  entries(): [string, any][] {
    return Array.from(this.cache.entries()).map(([key, item]) => [key, item.data]);
  }

  /**
   * 更新缓存项过期时间
   * 
   * @param key 缓存键
   * @param ttl 新的过期时间（毫秒）
   * @returns 是否更新成功
   */
  updateExpiry(key: string, ttl: number): boolean {
    try {
      const cacheItem = this.cache.get(key);
      
      // 检查缓存项是否存在
      if (!cacheItem) {
        return false;
      }

      // 更新过期时间
      cacheItem.expiresAt = Date.now() + ttl;
      this.cache.set(key, cacheItem);

      // 持久化缓存
      if (this.config.persistToStorage) {
        this.saveToStorage();
      }

      return true;
    } catch (error) {
      console.error('缓存过期时间更新失败:', error);
      return false;
    }
  }

  /**
   * 清理过期缓存
   * 
   * @returns 清理的缓存项数量
   */
  cleanup(): number {
    try {
      const now = Date.now();
      let count = 0;

      // 遍历缓存，删除过期项
      for (const [key, item] of this.cache.entries()) {
        if (now > item.expiresAt) {
          this.cache.delete(key);
          count++;
        }
      }

      // 持久化缓存
      if (count > 0 && this.config.persistToStorage) {
        this.saveToStorage();
      }

      return count;
    } catch (error) {
      console.error('缓存清理失败:', error);
      return 0;
    }
  }

  /**
   * 将缓存持久化到存储
   */
  private saveToStorage(): void {
    try {
      if (typeof window === 'undefined') {
        return;
      }

      // 将缓存转换为可序列化的对象
      const serializable = Array.from(this.cache.entries());
      
      // 保存到本地存储
      localStorage.setItem(this.config.storageKey, JSON.stringify(serializable));
    } catch (error) {
      console.error('缓存持久化失败:', error);
    }
  }

  /**
   * 从存储加载缓存
   */
  private loadFromStorage(): void {
    try {
      if (typeof window === 'undefined') {
        return;
      }

      // 从本地存储获取缓存
      const stored = localStorage.getItem(this.config.storageKey);
      
      if (!stored) {
        return;
      }

      // 解析缓存
      const serialized = JSON.parse(stored) as [string, CacheItem<any>][];
      
      // 重建缓存
      this.cache = new Map(serialized);
      
      // 清理过期项
      this.cleanup();
    } catch (error) {
      console.error('缓存加载失败:', error);
      
      // 如果加载失败，清空缓存
      this.cache.clear();
      
      // 删除可能损坏的存储
      if (typeof window !== 'undefined') {
        localStorage.removeItem(this.config.storageKey);
      }
    }
  }

  /**
   * 删除最旧的缓存项
   */
  private removeOldestItem(): void {
    try {
      let oldestKey: string | null = null;
      let oldestTimestamp = Infinity;

      // 查找最旧的缓存项
      for (const [key, item] of this.cache.entries()) {
        if (item.timestamp < oldestTimestamp) {
          oldestTimestamp = item.timestamp;
          oldestKey = key;
        }
      }

      // 删除最旧的缓存项
      if (oldestKey) {
        this.cache.delete(oldestKey);
      }
    } catch (error) {
      console.error('删除最旧缓存项失败:', error);
    }
  }

  /**
   * 启动自动清理定时器
   */
  private startCleanupTimer(): void {
    if (typeof window === 'undefined') {
      return;
    }

    // 清除现有定时器
    if (this.cleanupTimer) {
      clearInterval(this.cleanupTimer);
    }

    // 创建新定时器
    this.cleanupTimer = setInterval(() => {
      this.cleanup();
    }, this.config.cleanupInterval);
  }

  /**
   * 停止自动清理定时器
   */
  stopCleanupTimer(): void {
    if (this.cleanupTimer) {
      clearInterval(this.cleanupTimer);
      this.cleanupTimer = null;
    }
  }
} 